package org.ipp4j.core;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;

import org.ipp4j.core.standard.Tag;

public class Attribute {

	private static final String EMPTY_NAME = "";

	private Tag valueTag;
	private LinkedHashMap<String, List<byte[]>> nameValuePairs = new LinkedHashMap<String, List<byte[]>>();

	public Attribute(Tag valueTag, String name, byte[] value) {
		this.valueTag = valueTag;
		createIfEmpty(name).add(value);
	}

	public Attribute(Tag valueTag, String name, String value) {
		this(valueTag, name, value.getBytes());
	}

	public Attribute(Tag valueTag, String name, int value) {
		this(valueTag, name, IppUtils.convert(value));
	}

	public Attribute(Tag valueTag, String name, short value) {
		this(valueTag, name, IppUtils.convert(value));
	}

	public void updateValue(byte[] value) {
		createIfEmpty(EMPTY_NAME).add(value);
	}

	public void updateValue(String name, byte[] value) {
		if (EMPTY_NAME.equals(name)) {
			updateValue(value);
		} else {
			createIfEmpty(name).clear();
			createIfEmpty(name).add(value);
		}
	}

	public void addValue(String name, byte[] value) {
		createIfEmpty(name).add(value);
	}

	public byte[] getValue() {
		return retrieveFirstOne().getValue().get(0);
	}

	public String getValueString() {
		return getValueString(0);
	}

	public String getValueString(int index) {
		byte[] value = retrieveFirstOne().getValue().get(index);
		return new String(value);
	}

	public Tag getValueTag() {
		return valueTag;
	}

	public String getName() {
		return retrieveFirstOne().getKey();
	}

	public String getNameString() {
		return new String(retrieveFirstOne().getKey());
	}

	private Entry<String, List<byte[]>> retrieveFirstOne() {
		return nameValuePairs.entrySet().iterator().next();
	}

	private List<byte[]> createIfEmpty(String name) {
		if (!nameValuePairs.containsKey(name)) {
			nameValuePairs.put(name, new ArrayList<byte[]>());
		}
		return nameValuePairs.get(name);
	}

	public LinkedHashMap<String, List<byte[]>> getNameValuePairs() {
		return nameValuePairs;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append(valueTag.toString());
		builder.append("{");
		for (Entry<String, List<byte[]>> entry : nameValuePairs.entrySet()) {
			builder.append("(");
			builder.append(new String(entry.getKey()));
			builder.append("=");
			for (byte[] value : entry.getValue()) {
				builder.append(new String(value));
				builder.append("[");
				builder.append(toHexString(value));
				builder.append("],");
			}
			builder.append("),");
		}
		builder.append("}");
		return builder.toString();
	}

	private static String toHexString(byte[] value) {
		StringBuilder builder = new StringBuilder();
		for (byte b : value) {
			String hex = Integer.toHexString(b);
			if (hex.length() > 1) {
				builder.append("0");
			}
			builder.append(Integer.toHexString(b));
		}
		return builder.toString();
	}
}
